package beans.thread;

import java.util.LinkedList;
import java.util.List;

class Stack
{
	private final List<Object> list = new LinkedList<Object>();

	/**
	 * 出栈
	 * 
	 * @return
	 */
	public Object pop()
	{
		return list.remove(list.size() - 1);
	}

	/**
	 * 将元素压入栈
	 * 
	 * @param obj
	 */
	public void push(Object obj)
	{
		list.add(list.size(), obj);
	}

	public int size()
	{
		return list.size();
	}
}

class Producer extends Thread
{
	private Stack stack;

	public Stack getStack()
	{
		return stack;
	}

	/**
	 * 
	 * @param stack
	 */
	public void setStack(Stack stack)
	{
		this.stack = stack;
	}

	/**
	 * 生产者生产商品，当商品栈满时，通知消费者消费商品
	 */
	public void produce()
	{
		for (int i = 0; i < 100; i++)
		{
			// 同步stack
			synchronized (stack)
			{
				System.out.println("producer get the lock");
				// 这里指定存放商品的商品栈的最大容量为10
				while (stack.size() == 10)
				{
					try
					{
						// 将生产者线程持有stack对象的锁释放，并将生产者线程放到stack对象的等待池中
						stack.wait();
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}// 模拟生产者生产商品过程所需的时间
				try
				{
					Thread.sleep(1000);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				String goods = "goods" + stack.size();
				// 将生产的商品放到存放商品的商品栈中
				stack.push(goods);
				System.out.println("producer product " + goods);
				// 唤醒在stack对象等待池中的等待的所有线程
				stack.notifyAll();
			}
		}
	}

	@Override
	public void run()
	{
		produce();
	}
}

class Consumer extends Thread
{
	private Stack stack;

	public Stack getStack()
	{
		return stack;
	}

	public void setStack(Stack stack)
	{
		this.stack = stack;
	}

	/**
	 * 
	 * 消费者消费商品,当商品栈中为空时通知生产者生产商品
	 */
	public void consume()
	{
		for (int i = 0; i < 100; i++)
		{
			synchronized (stack)
			{
				System.out.println("consumer get the lock");
				while (stack.size() == 0)
				{
					try
					{
						stack.wait();
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}
				// 模拟消费者消费商品，所需的时间
				try
				{
					Thread.sleep(1000);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				Object obj = stack.pop();
				System.out.println("cosumer consume " + obj);
			}
		}
	}

	@Override
	public void run()
	{
		consume();
	}

	public static void main(String[] args)
	{
		Stack stack = new Stack();
		Consumer consumer = new Consumer();
		consumer.setStack(stack);
		Producer producer1 = new Producer();
		producer1.setStack(stack);
		Producer producer2 = new Producer();
		producer2.setStack(stack);
		consumer.start();
		producer1.start();
		producer2.start();
	}
}
